package team.cw.land.test.activiti.service.impl;


import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.*;
import org.activiti.engine.history.*;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import team.cw.land.test.activiti.dto.ActivitiDTO;
import team.cw.land.test.activiti.dto.ActivitiHistoryDTO;
import team.cw.land.test.activiti.dto.CommentDTO;
import team.cw.land.test.activiti.service.IActivitiService;
import team.cw.land.test.activiti.util.ActivitiUtils;
import team.cw.land.test.activiti.util.DateFormatUtil;

import javax.annotation.Resource;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ActivitiService implements IActivitiService {

    private static Logger logger = LoggerFactory.getLogger(ActivitiService.class);


    @Resource
    private ProcessEngine processEngine;

    @Resource
    private RuntimeService runtimeService;

    @Resource
    private TaskService taskService;

    @Resource
    private RepositoryService repositoryService;

    @Resource
    private HistoryService historyService;

    @Resource
    private FormService formService;

    @Override
    public String startProcess(String processName, Map<String,Object> userMap) {
        logger.info("===========启动流程============");
        ProcessInstance pi = runtimeService.startProcessInstanceByKey(processName,userMap);
        return pi.getId();
    }

    @Override
    public List<Task> myTaskList(String userName) {
        logger.info("===========查询用户需要处理的任务列表================");
        List<Task> taskList = taskService.createTaskQuery().taskAssignee(userName)
                .orderByTaskCreateTime().desc().list();
        return taskList;
    }

    @Override
    public void myCompleteProcess(String userName, String processId, String taskId, List<String> comments, Map<String, Object> map) {
        logger.info("===========完成流程================");
        taskService.setAssignee(taskId, userName);
        comments.forEach(comment ->{
            taskService.addComment(taskId,processId,comment);
        });
//        formService.submitTaskFormData(taskId, map);
        taskService.complete(taskId, map);
    }

    @Override
    public boolean isFinished(String processId) {
        return historyService.createHistoricProcessInstanceQuery().finished().processInstanceId(processId).count() > 0;
    }


    @Override
    public List<ActivitiDTO> getActivitiHistoryList(String processName) {
        logger.info("===========查询流程列表================");
        List<ActivitiDTO> activitiDTOS = new ArrayList<>();
        HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery();
        historicProcessInstanceQuery = StringUtils.isNotBlank(processName) ? historicProcessInstanceQuery.processDefinitionKey(processName) : historicProcessInstanceQuery;
        List<HistoricProcessInstance> historicProcessInstances = historicProcessInstanceQuery.orderByProcessInstanceEndTime().desc().list();
        historicProcessInstances.forEach(historicProcessInstance -> {
            ActivitiDTO activitiDTO = new ActivitiDTO();
            activitiDTO.setProcessId(historicProcessInstance.getId());
            activitiDTO.setProcessName(historicProcessInstance.getProcessDefinitionName());
            activitiDTO.setType(StringUtils.isNotBlank(historicProcessInstance.getEndActivityId()));
            activitiDTO.setStartTime(DateFormatUtil.dateFormat(historicProcessInstance.getStartTime()));
            activitiDTO.setEndTime(DateFormatUtil.dateFormat(historicProcessInstance.getEndTime()));
            activitiDTOS.add(activitiDTO);
        });
        return activitiDTOS;
    }

    @Override
    public List<ActivitiHistoryDTO> getActivitiHistoryInfo(String processId) {
        logger.info("=============查询流程详细历史数据================");
        List<ActivitiHistoryDTO> historyDTOS = new ArrayList<>();
        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().processInstanceId(processId).orderByHistoricActivityInstanceStartTime().asc().list();
        list.forEach(historicActivityInstance -> {
            Map<String,Object> map = new HashMap<>();
            List<CommentDTO>  commentDTOS = new ArrayList<>();
            //参数列表
            List<HistoricDetail> list1 = historyService.createHistoricDetailQuery().activityInstanceId(historicActivityInstance.getId()).orderByTime().asc().list();
            list1.forEach(instance1 -> {
                HistoricVariableUpdate variable = (HistoricVariableUpdate) instance1;
                map.put(variable.getVariableName(),variable.getValue());
            });
            //评论列表
            List<Comment> comments = taskService.getTaskComments(historicActivityInstance.getTaskId());
            comments.forEach(comment -> {
                CommentDTO commentDTO = new CommentDTO();
                commentDTO.setId(comment.getId());
                commentDTO.setTime(DateFormatUtil.dateFormat(comment.getTime()));
                commentDTO.setType(comment.getType());
                commentDTO.setMessage(comment.getFullMessage());
                commentDTOS.add(commentDTO);
            });
            ActivitiHistoryDTO historyDTO = new ActivitiHistoryDTO();
            historyDTO.setId(historicActivityInstance.getId());
            historyDTO.setActivityName(historicActivityInstance.getActivityName());
            historyDTO.setActivityType(historicActivityInstance.getActivityType());
            historyDTO.setTaskId(historicActivityInstance.getTaskId());
            historyDTO.setUserId(historicActivityInstance.getAssignee());
            historyDTO.setStartTime(DateFormatUtil.dateFormat(historicActivityInstance.getStartTime()));
            historyDTO.setEndTime(DateFormatUtil.dateFormat(historicActivityInstance.getEndTime()));
            historyDTO.setMap(map);
            historyDTO.setCommonList(commentDTOS);
            historyDTOS.add(historyDTO);
        });
        return historyDTOS;
    }

    @Override
    public byte[] getProcessImg(String processId) {
        logger.info("=============查询流程图================");
        HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processId).singleResult();

        BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());

        List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processId)
                .orderByHistoricActivityInstanceStartTime().asc().list();
        if(historicActivityInstanceList == null || historicActivityInstanceList.size() == 0) {
            return outputImg(bpmnModel, null, null,null);
        }
        // 已执行的节点ID集合(将historicActivityInstanceList中元素的activityId字段取出封装到executedActivityIdList)
        List<String> executedActivityIdList = historicActivityInstanceList.stream().map(item -> item.getActivityId()).collect(Collectors.toList());

        //获取流程定义
        List<String> flowIds = ActivitiUtils.getHighLightedFlows(bpmnModel, historicActivityInstanceList);
        /*
         * 输出图像，并设置高亮
         */
        return outputImg(bpmnModel, flowIds, executedActivityIdList,processId);
    }

    @Override
    public boolean deleteProcessId(String processId) {
        boolean finished = isFinished(processId);
        if(finished){
            historyService.deleteHistoricProcessInstance(processId);
        }else {
            runtimeService.deleteProcessInstance(processId,"");
            historyService.deleteHistoricProcessInstance(processId);
        }
        return true;
    }

    //输出图片流
    private byte[] outputImg(BpmnModel bpmnModel, List<String> flowIds, List<String> executedActivityIdList,String instanceId) {
        byte[] buffer = null;
        DefaultProcessDiagramGenerator processDiagramGenerator = (DefaultProcessDiagramGenerator) processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator();
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        try(InputStream imageStream = (InputStream)processDiagramGenerator.
                generateDiagram(bpmnModel, "png", executedActivityIdList, flowIds, "宋体", "微软雅黑", "黑体", null, 1.0);
        ){
            buffer =new byte[imageStream.available()];
            imageStream.read(buffer);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return buffer;
    }
}
